# Making a density map
# This Choropleth map shows the number of dentists by county. The labels on each county shape indicates the numercial sums of dentists. Even though the data used here is for BOD stand-alone part only, you can use the same code to make maps for Medicaid and CHIP. Here are the color schemes that I would like you to follow so that the color choices are uniform across all states:
# Medicaid - bluegreen
# CHIP - orangered
# Medicaid and CHIP combined - yellowgreen (for states that list Med and CHIP dentists in one category)
# BOD - bluepurple
import altair as alt
import pandas as pd
import geopandas as gpd
import json
alt.themes.enable('opaque')
pd.set_option('display.max_rows', 3200)
df_ruca = gpd.read_file(r"/Users/tinalu/Documents/ISyE Research/Shapes/Colorado RUCA Files")
df_ruca.columns
df_ruca.head(2)
# RUCA Private Insurance Map
#read in a CO chip file with sum of dentists in each tract
bod_ctdf = pd.read_csv('CO_BOD_census_tract.csv')
bod_ctdf.State_County_Tract_FIPS_Code = '0'+bod_ctdf.State_County_Tract_FIPS_Code.astype(str)
# bod_ctdf.State_County_Tract_FIPS_Code = bod_ctdf.State_County_Tract_FIPS_Code.astype(str)
df_ruca.GEOID = df_ruca.GEOID.astype(str)
# Merge the shapefiles with BOD file containing sums of dentists by tract
bod_ctdf2 = df_ruca.merge(bod_ctdf, left_on='GEOID', right_on = 'State_County_Tract_FIPS_Code', how='left')
#get the centroids so that labels of the number of dentists can be positioned there.
bod_ctdf2['centroid_lon'] = bod_ctdf2['geometry'].centroid.x
bod_ctdf2['centroid_lat'] = bod_ctdf2['geometry'].centroid.y
# convert the sums of dentists into strings so that they can be used as labels
bod_ctdf2['Count'] = bod_ctdf2['Count'].astype(str)
#convert data into json, since Altair expects the json data format.
choro_json = json.loads(bod_ctdf2.to_json())
#extract the part that Altair wants for mapping
choro_data = alt.Data(values=choro_json['features'])
#function to define how the map will be made.
def gen_map(geodata, color_column, title, tooltip):
'''Generates map of counties with labels'''
# Add Base Layer
base = alt.Chart(geodata, title = title).mark_geoshape(
fill='white',
stroke='black',
strokeWidth=1
).encode(
).properties(
width=800,
height=800
)
choro = alt.Chart(geodata).mark_geoshape(stroke='black').encode(
color=alt.Color(color_column,
legend=alt.Legend(title="Number of Dentists"),
scale=alt.Scale(scheme='bluepurple')
), tooltip=[alt.Tooltip('properties.GEOID:O', title='Census Tract'),
alt.Tooltip('properties.Count:Q', title='Number of Dentists')]
).transform_lookup(
lookup='properties',
from_=alt.LookupData(geodata, 'properties', ['Count'])
)
# Add Labels Layer. Here they are the sums of dentists per census tract
labels = alt.Chart(geodata).mark_text(baseline='top'
).properties(
width=400,
height=400
).encode(
longitude='properties.centroid_lon:Q',
latitude='properties.centroid_lat:Q',
text='properties.Count:O',
size=alt.value(10),
opacity=alt.value(1)
)
return base + choro #use this line if you don't want the text labels
# return base + choro + labels #use this line if you want the text labels
#Call function, pass the appropriate parameters.
CO_private_ruca_map = gen_map(geodata=choro_data, color_column='properties.Count:Q',
title='Colorado Number of Dentists per Census Tract: Accepting Private Insurance Only', # TODO: Change state
tooltip=['properties.GEOID:O','properties.Count:Q'])
CO_private_ruca_map